package com.catsic.core.utils;
import java.io.File; 
import java.io.IOException;
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.Enumeration; 
import java.util.List; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 
 

/**
 * ClassName: PackageUtil
 * Description: TODO 获取包名下所有类名
 * date: 2014-3-5 上午10:25:49
 * author: Jay
 */
 
public class PackageUtil { 
 
 
    /*
     * 获取某包下（包括该包的所有子包）所有类
     * @param packageName 包名
     * @return 类的完整名称
      
    public static List<String> getClassName(String startpackageName,String endpackagename) { 
        return getClassName(startpackageName, endpackagename); 
    } */
 
    /**
     * 获取某包下所有类
     * @param packageName 包名
     * @param endpackagename 包尾名
     * @return 类的完整名称
     */ 
    public static List<String> getClassName(String packageName, String endpackagename) { 
        List<String> fileNames = new ArrayList<String>(); 
        ClassLoader loader = Thread.currentThread().getContextClassLoader(); 
        String packagePath = packageName.replace(".", "/"); 
        try {
        	/* 查询所有资源路径下符合条件的类 */
        	Enumeration<URL> urls = loader.getResources(packagePath);
 
	        while (urls.hasMoreElements()) {
	            URL url = urls.nextElement();
	            String type = url.getProtocol(); 
	            if (type.equals("file")) { 
	                fileNames.addAll( getClassNameByFile(url.getPath(), packageName,endpackagename) ); 
	            } else if (type.equals("jar")) { 
	            	fileNames.addAll(  getClassNameByJar(url.getPath(), endpackagename) ); 
	            } 
	            
	        }
	          
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        if( fileNames.size()<1 ) { 
            fileNames = getClassNameByJars(((URLClassLoader) loader).getURLs(), packagePath, endpackagename); 
        } 
        return fileNames; 
    } 
 
    /**
     * 从项目文件获取某包下所有类
     * @param filePath 文件路径
     * @param className 类名集合
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     */ 
    private static List<String> getClassNameByFile(String filePath, String startpackagename, String endpackagename) { 
        List<String> myClassName = new ArrayList<String>(); 
        File file = new File(filePath); 
        File[] childFiles = file.listFiles(); 
        for (File childFile : childFiles) {
        	//当包名不包括通配符，只遍历当前目录
        	if(endpackagename==null||endpackagename.equals("")){
        		if (childFile.isFile()) {
	        		String childFilePath = childFile.getPath(); 
	                if (childFilePath.endsWith(".class")) { 
	                	startpackagename = startpackagename.replace(".", "\\");
	                    childFilePath = childFilePath.substring(childFilePath.indexOf("startpackagename"), childFilePath.lastIndexOf(".")); 
	                    childFilePath = childFilePath.replace("\\", "."); 
	                    myClassName.add(childFilePath); 
	                } 
                }
        	}else{
        		//包名包括通配符
	            if (childFile.isDirectory()) { 
	            	//如果是目录，迭代
	                    myClassName.addAll(getClassNameByFile(childFile.getPath(), startpackagename, endpackagename)); 
	            } else { 
	            	String childFilePath = childFile.getPath(); 
	            	//如果是文件，判断是否为指定最终目录
	            	if(childFilePath.indexOf(endpackagename)>0)
	                if (childFilePath.endsWith(".class")&&(childFilePath.lastIndexOf("\\"+endpackagename+"\\")==childFilePath.lastIndexOf("\\")-(endpackagename.length()+1))) { 
	                	startpackagename = startpackagename.replace(".", "\\");
	                    childFilePath = childFilePath.substring(childFilePath.indexOf(startpackagename), childFilePath.lastIndexOf(".")); 
	                    childFilePath = childFilePath.replace("\\", "."); 
	                    myClassName.add(childFilePath); 
	                } 
	            } 
            }
        } 
 
        return myClassName; 
    } 
 
    /**
     * 从jar获取某包下所有类
     * @param jarPath jar文件路径
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     */ 
    private static List<String> getClassNameByJar(String jarPath, String endpackagename) { 
        List<String> myClassName = new ArrayList<String>(); 
        String[] jarInfo = jarPath.split("!"); 
        String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/")); 
        String packagePath = jarInfo[1].substring(1); 
        try { 
            @SuppressWarnings("resource")
			JarFile jarFile = new JarFile(jarFilePath); 
            Enumeration<JarEntry> entrys = jarFile.entries(); 
            while (entrys.hasMoreElements()) { 
                JarEntry jarEntry = entrys.nextElement(); 
                String entryName = jarEntry.getName();
                //如果是类
                if (entryName.endsWith(".class")) { 
                	//如果最后一个包名是
                    if (endpackagename!=null&&endpackagename.length()>0) { 
                        if (entryName.startsWith(packagePath)&&entryName.lastIndexOf("."+endpackagename+".")==entryName.lastIndexOf(".")-(endpackagename.length()+1)) { 
                            entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf(".")); 
                            myClassName.add(entryName); 
                        } 
                    } else { 
                        int index = entryName.lastIndexOf("/"); 
                        String myPackagePath; 
                        if (index != -1) { 
                            myPackagePath = entryName.substring(0, index); 
                        } else { 
                            myPackagePath = entryName; 
                        } 
                        if (myPackagePath.equals(packagePath)) { 
                            entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf(".")); 
                            myClassName.add(entryName); 
                        } 
                    } 
                } 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return myClassName; 
    } 
 
    /**
     * 从所有jar中搜索该包，并获取该包下所有类
     * @param urls URL集合
     * @param packagePath 包路径
     * @param childPackage 是否遍历子包
     * @return 类的完整名称
     */ 
    private static List<String> getClassNameByJars(URL[] urls, String packagePath, String endpackagename) { 
        List<String> myClassName = new ArrayList<String>(); 
        if (urls != null) { 
            for (int i = 0; i < urls.length; i++) { 
                URL url = urls[i]; 
                String urlPath = url.getPath(); 
                // 不必搜索classes文件夹 
                if (urlPath.endsWith("classes/")) { 
                    continue; 
                } 
                String jarPath = urlPath + "!/" + packagePath; 
                myClassName.addAll(getClassNameByJar(jarPath, endpackagename)); 
            } 
        } 
        return myClassName; 
    } 
    
    
    public static void main(String[] args) throws Exception { 
        String startpackageName = "com.catsic"; 
        String endpackageName = "rmi";
        // List<String> classNames = getClassName(packageName); 
        List<String> classNames = getClassName(startpackageName, endpackageName); 
        if (classNames != null) { 
            for (String className : classNames) { 
                System.out.println(className); 
            } 
        } 
    } 
} 
